home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1985-1992 New York University
- *
- * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
- * warranty (none) and distribution info and also the GNU General Public
- * License for more details.
-
- */
- #include "4.h"
- #include "attr.h"
- #include "setprots.h"
- #include "evalprots.h"
- #include "errmsgprots.h"
- #include "dclmapprots.h"
- #include "sspansprots.h"
- #include "nodesprots.h"
- #include "miscprots.h"
- #include "smiscprots.h"
- #include "utilprots.h"
- #include "chapprots.h"
-
- static int constraint_kind(Symbol);
- static void make_constrained_node(Node, Symbol, int);
- static void dereference_node(Node, Symbol);
- static Symbol resolve2_attr(Node, Symbol);
- static int in_univ_attributes(int);
- static void check_bounds_in_range(Node, Node, Symbol);
- static void check_array_conversion(Node, Symbol, Symbol);
- static int reads_prefix(int, Symbol);
-
- int in_type_classes(Symbol sym) /*;in_type_classes*/
- {
- /* return true if sym in type_classes, as defined in check_type*/
- /* New procedure aqdded for c version */
- return (
- sym == symbol_boolean_type
- || sym == symbol_discrete_type
- || sym == symbol_integer_type
- || sym == symbol_real_type
- || sym == symbol_universal_type);
- }
-
- void check_type_i(Node expn) /*;check_type_i*/
- {
- /* check_type('integer_type', expn) */
- check_type(symbol_integer_type, expn);
- }
-
- void check_type_r(Node expn) /*;check_type_r*/
- {
- /* check_type('real_type', expn) */
- check_type(symbol_real_type, expn);
- }
-
- void check_type_d(Node expn) /*;check_type_d*/
- {
- /* check_type('discrete_type', expn) */
- check_type(symbol_discrete_type, expn);
- }
-
- void check_type_u(Node expn) /*;check_type_u*/
- {
- /* check_type('universal_type', expn) */
- check_type(symbol_universal_type, expn);
- }
-
- void check_type(Symbol context_type, Node expn) /*;check_type*/
- {
- /* This procedure performs type checking and operator disambiguation.
- * -expn- is an expression tree, which must have the type -context_type-.
- * This procedure is called in all contexts where the type of
- * an expression is known a priori : assignments, conditionals, etc.
- * The procedure returns the annotated tree for -expn-, labelling each
- * node with its unique type, and resolving overloaded constructs where
- * needed.
- * Some contexts require that a type belong to a class of types instead
- * of one specific type. For example, a condition must be of a boolean
- * type, not just BOOLEAN.
- */
-
- Set types, otypes;
- Symbol t, old_context;
- Forset fs1;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : check_type");
-
- N_TYPE(expn) = symbol_any; /*By default.*/
- noop_error = FALSE;
-
- resolve1(expn); /* Bottom-up pass.*/
-
- if (noop_error) {
- noop_error = FALSE; /* error emitted already*/
- N_TYPE(expn) = symbol_any;
- return;
- }
-
- types = N_PTYPES(expn);
- old_context = context_type;
- if (in_type_classes(context_type)) {
- /* Keep only those that belong to this class.*/
- otypes = set_copy(types);
- types = set_new(0);
- FORSET(t = (Symbol), otypes, fs1);
- if (compatible_types(t, context_type))
- types = set_with(types, (char *) t);
- ENDFORSET(fs1);
- set_free(otypes);
-
- if (set_size(types) > 1) {
- /* May be overloaded operator: user_defined one hides predefined.*/
- /* types -:= univ_types */
- otypes = set_copy(types);
- types = set_new(0);
- FORSET(t = (Symbol), otypes, fs1);
- if (t != symbol_universal_integer && t!= symbol_universal_real)
- types = set_with(types, (char *)t);
- ENDFORSET(fs1);
- set_free(otypes);
- }
-
- if (set_size(types) == 1) {
- context_type = (Symbol) set_arb (types);
- set_free(types);
- }
- else {
- type_error(set_new1((char *) symbol_any), context_type,
- set_size(types), expn);
- N_TYPE(expn) = symbol_any;
- set_free(types);
- return;
- }
- }
-
- resolve2(expn, context_type);
-
- if (noop_error) {
- noop_error = FALSE; /* error emitted already*/
- return;
- }
-
- /* Now emit a constraint qualification if needed.*/
- if (! in_type_classes(old_context)) apply_constraint(expn, context_type);
- if (! in_univ_types(context_type)) eval_static(expn);
- }
-
- static int constraint_kind(Symbol typ) /*;constraint_kind*/
- {
- Symbol d;
-
- if (cdebug2 > 3) {
- TO_ERRFILE("AT PROC : constraint_kind");
- }
- /* Note that the use of '' in SETL version is translated to zero in
- * the c version. This use of '' is common only to this routine and
- * the next following one.
- */
- if (is_unconstrained(typ) || in_univ_types(typ)) return as_opt;
- if (is_scalar_type(typ)) {
- if (NATURE(typ) == na_enum) return as_opt;
- else return as_qual_range;
- }
- if (is_array(typ)) {
- if (full_others || NATURE(scope_name) == na_record)
- return as_qual_index;
- else return as_opt;
- }
- if (is_record(typ)) {
- if (has_discriminants(typ)) return as_qual_discr;
- else return as_opt;
- }
- if (is_access(typ)) {
- d = (Symbol) designated_type(typ);
- if (is_scalar_type(d)) return as_opt;
- else if (is_unconstrained(d)) return as_opt;
- else if (is_array(d)) {
- return as_qual_aindex;
- }
- else if (is_record(d)) {
- if (has_discriminants(d)) return as_qual_adiscr;
- else return as_opt;
- }
- }
- return as_opt;
- }
-
- void apply_constraint(Node expn, Symbol typ) /*;apply_constraint*/
- {
- int k, constraint;
-
- if (cdebug2 > 3) {
- TO_ERRFILE("AT PROC : apply constraint");
- }
-
- constraint = constraint_kind(typ);
- /* test of constraint != 0 corresponds to encoding assigned in previous
- * procedure
- */
- k = N_KIND(expn);
-
- /* If node is insert node, lone descendant is original expression.*/
- if (k == as_insert) apply_constraint(N_AST1(expn), typ);
-
- if (k == as_subtype || k == as_parenthesis || constraint == as_opt)
- return;
- /* the two cases have to be distinguished : a'first..a'last and a'b
- * in an aggregate, where a qual_range doesn't make any sens.
- */
- if (k == as_attribute
- && ((int) attribute_kind(expn) == ATTR_T_RANGE
- || (int) attribute_kind(expn) == ATTR_O_RANGE)
- && constraint == as_qual_range)
- return;
-
- if (k == as_ivalue || (N_TYPE(expn) != typ)
- || (k == as_array_aggregate)
- || (k == as_new && N_AST2(expn) == OPT_NODE)) {
-
- /* The two following lines were in the Setl version : We don't have
- * to keep them since qual_a* is tranformed in qual_* in the code
- * generator
- * if (is_access (typ)) {type_const = (Symbol) designated_type (typ); }
- * else { type_const = typ; }
- */
- make_constrained_node(expn, typ, constraint);
- }
- }
-
- static void make_constrained_node(Node expn, Symbol typ, int constraint)
- /*;make_constrained_node*/
- {
- Node e_node;
-
- e_node = copy_node(expn);
- N_KIND(expn) = constraint;
- N_AST1(expn) = e_node;
- if (N_AST2_DEFINED(constraint)) N_AST2(expn) = (Node)0;
- if (N_AST3_DEFINED(constraint)) N_AST3(expn) = (Node)0;
- if (N_AST4_DEFINED(constraint)) N_AST4(expn) = (Node)0;
- N_TYPE(expn) = typ;
- }
-
- int in_priv_types(Symbol s) /*;in_priv_types*/
- {
- return (s == symbol_private || s == symbol_limited_private);
- }
-
- void resolve1(Node expn) /*;resolve1*/
- {
- /* This procedure performs the first, bottom-up pass of the type checking
- * and overload resolution. It annotates the expression tree with the
- * attribute N_PTYPES(expn), corresponding to the possible types of the
- * expression.
- */
-
- Fortup ft1;
- Forset fs1, fs2;
- unsigned int op_name;
- int exists, i, j, k, tmp1, nat;
- Symbol name, target_type;
- Set names, op_types, array_types;
- Tuple tmp;
- Set tset;
- Node arg, aggregate_node;
- Tuple arg_list;
- Symbol n_t;
- Node lit_name;
- Symbol n;
- Node op_node, args_node;
- Set possible_types;
- Node arg2;
- Symbol nam;
- Node constraint;
- Set ts;
- Symbol t;
- Node ac_expn, type_id;
- Symbol type_mark;
- Symbol desig_type;
- Node c_expr, arg1;
- Node t_node;
- Node e;
- Symbol to_type;
- Set types;
- Node type_node;
- Node low;
- Node high;
- Set t_low, t_high;
- Symbol t1, t2, it, typ;
- Node call_node, index_node;
- Span save_span;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : resolve1 ");
-
- /*if (noop_error ? false) then return; end if; */
- /* TODO: check why noop_error assumed possible non_boolean in above */
- if (noop_error) {
- N_PTYPES(expn) = set_new1((char *) symbol_any);
- return;
- }
-
- op_name = N_KIND(expn);
-
- if (cdebug2 > 3) {
- #ifdef IBM_PC
- printf(" resolve1 %p %s\n", expn, kind_str(op_name));
- #else
- printf(" resolve1 %ld %s\n", expn, kind_str(op_name));
- #endif
- }
-
- switch (op_name) {
- case as_simple_name:
- name = N_OVERLOADED(expn) ? (Symbol) 0 : N_UNQ(expn);
- if (name != (Symbol)0) {
-
- n_t = TYPE_OF(name);
- nat = NATURE(name);
- if ( nat == na_obj
- || nat == na_constant
- || nat == na_in
- || nat == na_inout
- || nat == na_out
- || nat == na_task_obj
- || nat == na_task_obj_spec
- || nat == na_task_type
- || nat == na_task_type_spec) {
- N_PTYPES(expn) = set_new1((char *) n_t);
- }
- else if (nat == na_type || nat == na_subtype
- || nat == na_enum || nat == na_record
- || nat == na_array || nat == na_access) {
- N_PTYPES(expn) = set_new1((char *) symbol_any);
- pass1_error_id("Invalid use of type %", name, "4.4", expn);
- }
- else if (nat == na_discriminant) {
- /* A discriminant reference can only appear within a */
- /* record definition. The rec.type in noted on the node. */
- save_span = get_left_span(expn);
- N_KIND(expn) = as_discr_ref;
- N_AST1(expn) = new_name_node(SCOPE_OF(name));
- N_AST2(expn) = N_AST4(expn) = (Node) 0;
- set_span(N_AST1(expn), save_span);
- N_PTYPES(expn) = set_new1((char *) n_t);
- }
-
- else if (nat == na_void) {
- N_PTYPES(expn) = set_new1((char *)symbol_any);
- pass1_error_id("premature use of %", name, "8.3", expn);
- return;
- }
- else {
- N_PTYPES(expn) = set_new1((char *) symbol_any);
- pass1_error_id("Invalid use of identifier %", name,
- "4.4", expn);
- }
- }
- else {
- /* The simple name is overloaded: case of a literal or para-*/
- /* meterless function. Reformat with null param. list.*/
- lit_name = copy_node(expn);
- args_node = node_new(as_list);
- N_LIST(args_node) = tup_new(0);
- N_KIND(expn) = as_call;
- N_AST1(expn) = lit_name;
- N_AST2(expn) = args_node;
- resolve1(expn);
- }
- break;
- case as_character_literal:
- N_PTYPES(expn) = set_new(set_size(N_NAMES(expn)));
- FORSET(n = (Symbol), N_NAMES(expn), fs1);
- N_PTYPES(expn) = set_with(N_PTYPES(expn), (char *) TYPE_OF(n));
- ENDFORSET(fs1);
- break;
- case as_op:
- case as_un_op:
- case as_call:
- /* Overloaded constructs. */
-
- op_node = N_AST1(expn);
- args_node = N_AST2(expn);
-
- FORTUP(arg = (Node), N_LIST(args_node), ft1);
- resolve1(arg);
- check_range_attribute(arg); /* a no-no */
- ENDFORTUP(ft1);
- names = N_NAMES(op_node);
- result_types(expn);
- if (noop_error); /* Previous error. */
- else if (set_size(N_PTYPES(expn)) == 0)
- type_error(names, (Symbol) 0, 0, expn);
-
- /* All other cases are basic operations on arrays, record, aggregates */
- /* attributes, subtypes, conversions and qualifications. */
- break;
- case as_name:
- find_old(expn);
- resolve1(expn);
- break;
- case as_int_literal:
- N_PTYPES(expn) = set_new1((char *)symbol_universal_integer);
- break;
- case as_real_literal:
- N_PTYPES(expn) = set_new1((char *) symbol_universal_real);
- break;
- case as_string_literal:
- N_PTYPES(expn) = set_new1((char *) symbol_string_type);
- break;
- case as_null:
- N_PTYPES(expn) = find_access_types();
- break;
- case as_aggregate:
- /* Verify that the list of choices is properly formatted, and
- * collect all possible aggregate types. The types of the in-
- * dividual choices are not used to resolve the aggregate type.
- */
- arg_list = N_LIST(expn);
- exists = FALSE;
- FORTUPI(arg = (Node), arg_list, i, ft1);
- if (N_KIND(arg) == as_choice_list) {
- exists = TRUE;
- break;
- }
- ENDFORTUP(ft1);
- if (exists) {
- exists = FALSE;
- for (j = i + 1; j <= tup_size(arg_list); j++) {
- arg2 = (Node) arg_list[j];
- if (N_KIND(arg2) != as_choice_list) {
- exists = TRUE;
- break;
- }
- }
- }
- /* if (exists arg = arg_list(i) | N_KIND(arg) = as_choice_list)
- * and(exists arg2 in arg_list(i+1..) |
- * N_KIND(arg2) /= as_choice_list)
- */
- if (exists) {
- Tuple t, t1;
- pass1_error(
- "positional associations must appear first in aggregate", "4.3",
- arg2);
- t = tup_new(i);
- /* N_LIST(expn) = N_LIST(expn)(1..i); */
- t1 = N_LIST(expn);
- for (j = 1; j <= i; j++)
- t[i] = t1[i];
- N_LIST(expn) = t;
- }
- /* collect all possible aggregate types. */
- N_PTYPES(expn) = find_agg_types();
- break;
- case as_index:
- possible_types = set_new(0);
- {
- Symbol t;
- FORSET(t = (Symbol), valid_array_expn(expn), fs1);
- possible_types = set_with(possible_types,
- (char *) component_type(t));
- ENDFORSET(fs1);
- }
- if (set_size(possible_types) == 0)
- pass1_error("type mismatch in indexing", "4.1.1", expn);
- N_PTYPES(expn) = possible_types;
- break;
- case as_slice:
- /* Slicing operations are equivalent to indexing operations,
- * for type checking purposes. We simply reformat the result
- * of type checking, so that the result type of the slice is
- * the base type of the array expression. If this type is an
- * access type, we must of course dereference it.
- */
- possible_types = valid_array_expn(expn);
-
- if (set_size(possible_types) == 0)
- pass1_error("type mismatch in slice", "4.1.2", expn);
-
- /* N_PTYPES(expn) := {base_type(t) : t in possible_types}; */
- tset = set_new(0);
- {
- Symbol t;
- FORSET(t = (Symbol), possible_types, fs1);
- tset = set_with(tset, (char *) t);
- ENDFORSET(fs1);
- }
- set_free(possible_types);
- N_PTYPES(expn) = tset;
- break;
- case as_selector:
- valid_selected_expn(expn);
- break;
- case as_in:
- case as_notin:
- /* The second argument of membership operators is a type_mark or */
- /* a range. */
- op_node = N_AST1(expn);
- args_node = N_AST2(expn);
- tmp = N_LIST(args_node);
- arg1 = (Node) tmp[1];
- arg2 = (Node) tmp[2];
-
- resolve1(arg1);
- if (N_KIND(arg2) == as_range_expression) {
- find_old(arg2);
- k = N_KIND(arg2);
- if (k != as_simple_name && k != as_attribute) {
- pass1_error("invalid argument for membership operator",
- "4.4", arg2);
- return;
- }
- nam = N_UNQ(arg2);
- t = base_type(nam);
- if (in_priv_types(t)) t = nam;
- N_PTYPES(arg2) = set_new1((char *) t);
- /* Missing: range attribute. */
- }
- else {
- if (N_KIND(arg2) != as_attribute) {
- /* Argument is a range: reformat as subtype of some type. */
- constraint = copy_node(arg2);
- N_KIND(arg2) = as_subtype;
- N_AST1(arg2) = OPT_NODE;
- N_AST2(arg2) = constraint;
- }
- resolve1(arg2);
-
- /* ts := {t in N_PTYPES(arg2) | is_scalar_type(t)}; */
- ts = set_new(0);
- {
- Symbol t;
- FORSET(t = (Symbol), N_PTYPES(arg2), fs1);
- if (is_scalar_type(t))
- ts = set_with(ts, (char *) t);
- ENDFORSET(fs1);
- }
- if (set_size(ts) == 0) {
- #ifdef ERRNUM
- errmsgn(234, 235, arg2);
- #else
- errmsg("bounds of range for membership op must be scalar",
- "4.4", arg2);
- #endif
- }
- else N_PTYPES(arg2) = ts;
- }
- /* Now resolve the expression as for any other operator. */
-
- {
- Set op_name_set;
- N_KIND(expn) = as_op;
- op_name_set = op_name == as_in ? set_new1((char *)symbol_in)
- : set_new1((char *)symbol_notin);
- N_NAMES(op_node) = op_name_set;
- result_types(expn);
- if (noop_error);
- else if (set_size(N_PTYPES(expn)) == 0)
- type_error(op_name_set, (Symbol)0, 0, expn);
- }
- break;
- case as_all:
- /* dereference operations must apply to objects of access type.
- * The type yielded is obtained by dereferencing the type descrip
- * tor of the access object.
- */
- ac_expn = N_AST1(expn);
-
- resolve1(ac_expn);
- /* ??possible_types := {designated_type(t): t in N_PTYPES(ac_expn)
- * | is_access(t)};
- */
- possible_types = set_new(0);
- {
- Symbol t;
- FORSET(t = (Symbol), N_PTYPES(ac_expn), fs1);
- if (is_access(t))
- possible_types = set_with(possible_types,
- (char *) designated_type(t));
- ENDFORSET(fs1);
- }
- if (set_size(possible_types) == 0) {
- pass1_error("Expect access type for dereference",
- "3.8", ac_expn);
- }
- N_PTYPES(expn) = possible_types;
- break;
- case as_new:
- /* the elaboration of the subtypes may produce additional
- * anonymous types. These are emitted later on (see resolve2)
- * and here are just collected and discarded.
- */
- newtypes = tup_with(newtypes, (char *)tup_new(0));
- desig_type = make_subtype(expn);
- {
- Tuple junk = (Tuple)tup_frome(newtypes);
- tup_free(junk);
- }
- type_id = N_AST1(expn);
- constraint = N_AST2(expn);
-
- type_mark = N_UNQ(type_id);
- if ((constraint == OPT_NODE) &&(is_unconstrained(type_mark))) {
- pass1_error_l("Constraint required in allocator when",
- "initialization is absent", "4.8", expn);
- return;
- }
- else /* use name of generated subtype to label allocator */
- N_UNQ(type_id) = desig_type;
-
- check_fully_declared(desig_type);
-
- /* Rebuild node as having a designated type and no aggregate. */
- if (constraint != OPT_NODE) {
- type_node = copy_node(expn);
- N_UNQ(type_node) = desig_type;
- N_KIND(type_node) = as_subtype_decl;
- }
- else type_node = type_id;
- N_AST1(expn) = type_node;
- N_AST2(expn) = OPT_NODE;
-
- /* N_PTYPES(expn) := {a in find_access_types() |
- * compatible_types(desig_type, designated_type(a))};
- */
- {
- Set s;
- Symbol a;
- s = set_new(0);
- FORSET(a = (Symbol), find_access_types(), fs1);
- if (compatible_types(desig_type, designated_type(a)))
- s = set_with(s, (char *) a);
- ENDFORSET(fs1);
- N_PTYPES(expn) = s;
- }
- break;
- case as_new_init:
- /* Allocator given by a type mark and an explicit aggregate. */
-
- type_id = N_AST1(expn);
- aggregate_node = N_AST2(expn);
- find_type(type_id);
- desig_type = N_UNQ(type_id);
- if (!is_type(desig_type)) {
- pass1_error("invalid type mark in allocator", "4.8", type_id);
- return;
- }
- else
- if (is_limited_type(desig_type)) {
- pass1_error_l("initial value not allowed on an ",
- "allocator for a limited type", "7.4.4", type_id);
- return;
- }
- if (N_KIND(aggregate_node) == as_parenthesis) {
- /*Remove parenthesis which is an artifact of parsing.*/
- aggregate_node = N_AST1(aggregate_node);
- N_AST2(expn) = aggregate_node;
- }
- resolve1(aggregate_node);
- /* ??N_PTYPES(expn) = {a in find_access_types() |
- * compatible_types(desig_type, designated_type(a))}; $$ES151
- */
- {
- Symbol a;
- Set s;
- s = set_new(0);
- FORSET(a = (Symbol), find_access_types(), fs1);
- if (compatible_types(desig_type, designated_type(a)))
- s = set_with(s, (char *) a);
- ENDFORSET(fs1);
- N_PTYPES(expn) = s;
- }
- N_KIND(expn) = as_new; /* for common processing. */
- break;
- case as_choice_list:
- /* This is used only for the arguments to calls and not for */
- /* aggregates which are handled in complete_r_aggregate. */
-
- c_expr = N_AST2(expn);
- resolve1(c_expr);
- #ifdef TBSL
- -- is copy of N_TYPES needed below ds 8-jan-85
- #endif
- N_PTYPES(expn) = N_PTYPES(c_expr);
- break;
- case as_attribute:
- resolv_attr(expn);
- break;
- case as_qual_range:
- /* When qual_range appears in an expression, the bounds have */
- /* been type-checked. Simple extract the known result type. */
- N_PTYPES(expn) = set_new1((char *) N_TYPE(expn));
- break;
- case as_convert:
- /* The result type is the type mark of the conversion. */
-
- t_node = N_AST1(expn);
- arg = N_AST2(expn);
- tmp1 = N_KIND(arg);
- target_type = N_UNQ(t_node);
- if (tmp1 == as_null || tmp1 == as_new || tmp1 == as_new_init
- || tmp1 == as_aggregate || tmp1 == as_string_literal) {
- pass1_error("invalid expression for conversion",
- "4.6(3)", arg);
- return;
- }
- else if (is_incomplete_type(target_type)) {
- pass1_error("premature use of private type in expression",
- "7.4.1(4)", t_node);
- }
- else {
- resolve1(arg);
- N_PTYPES(expn) = set_new1((char *)target_type);
- }
- break;
- case as_qualify:
-
- t_node = N_AST1(expn);
- arg = N_AST2(expn);
- to_type = N_UNQ(t_node);
- if (!is_type(to_type)) {
- pass1_error("Expect type mark in qualified expression",
- "4.7", t_node);
- return;
- }
- else if (in_open_scopes(to_type) && is_task_type(to_type)) {
- pass1_error_id("invalid use of type % within its own body",
- to_type, "9.1", t_node);
- return;
- }
- else if (is_incomplete_type(to_type)) {
- pass1_error("premature use of private type in expression",
- "7.4.1(4)", t_node);
- return;
- }
- else N_PTYPES(expn) = set_new1((char *) to_type);
-
- resolve1(arg);
-
- if (noop_error) return;
- else types = N_PTYPES(arg);
-
- exists = FALSE;
- {
- Symbol t;
- FORSET(t = (Symbol), types, fs1);
- if (compatible_types(to_type, t)) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- }
- if (!exists) {
- pass1_error("Expression has wrong type for qualification",
- "4.7", arg);
- }
- break;
- case as_subtype:
- /* For a subtype expression, the bounds expressions must be
- * checked against the specified type, if any, or against the
- * type required by context.
- */
- type_node = N_AST1(expn);
- constraint = N_AST2(expn);
- if (N_KIND(constraint) == as_attribute)
- t_low = t_high = N_PTYPES(constraint);
- else {
- low = N_AST1(constraint);
- high = N_AST2(constraint);
- resolve1(low);
- resolve1(high);
- t_low = N_PTYPES(low);
- t_high = N_PTYPES(high);
- }
- if (type_node == OPT_NODE) {
- /* Case of a range expression with no named type. Validate
- * the bounds against each other, and return the possible types.
- */
- possible_types = set_new(0);
- FORSET(t1 = (Symbol), t_low, fs1);
- FORSET(t2 = (Symbol), t_high, fs2);
- it = intersect_types(t1, t2);
- if (it != (Symbol)0)
- possible_types = set_with(possible_types, (char *)it);
- ENDFORSET(fs2);
- ENDFORSET(fs1);
- }
- else {
- int exists1, exists2;
- /* Subtype of a specified type. Validate the bounds against */
- /* it. */
- typ = N_UNQ(type_node);
- possible_types = set_new1((char *) typ);
- /* if (not exists t1 in t_low |compatible_types(typ, t1))
- * or (not exists t2 in t_high|compatible_types(typ, t2)) then
- */
- exists1 = exists2 = FALSE;
- FORSET(t1 = (Symbol), t_low, fs1);
- if (compatible_types(typ, t1)) {
- exists1 = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists1 == TRUE) {
- FORSET(t2 = (Symbol), t_high, fs1);
- if (compatible_types(typ, t2)) {
- exists2 = TRUE;
- break;
- }
- ENDFORSET(fs1);
- }
- if (!exists1 || !exists2) {
- pass1_error("Invalid types in bounds for range",
- "3.5, 4.1.2", expn);
- }
- }
- N_PTYPES(expn) = possible_types;
- break;
- case as_parenthesis:
- /* A parenthesised expression carries a special operator, in
- * order to distinguish it from a variable.(Thus(X) is not a
- * valid OUT parameter for a procedure, and(D) is not a valid
- * use of a discriminant name).
- */
- e = N_AST1(expn);
- resolve1(e);
- N_PTYPES(expn) = N_PTYPES(e);
- break;
- case as_call_or_index:
- /* A call to a parameterless function that returns an array can
- * overload a call to a function call with arguments. Resolve
- * each of the trees independently.
- */
- call_node = N_AST1(expn);
- index_node = N_AST2(expn);
- op_node = N_AST1(call_node);
- args_node = N_AST2(call_node);
- FORTUP(arg = (Node), N_LIST(args_node), ft1);
- resolve1(arg);
- ENDFORTUP(ft1);
- result_types(call_node);
- op_types = N_PTYPES(call_node);
- #ifdef TBSN
- if (cdebug2 > 3) TO_ERRFILE('op_types ' + str op_types);
- #endif
- array_types = set_new(0);
- FORSET(t = (Symbol), valid_array_expn(index_node), fs1);
- t = (Symbol)component_type(t);
- array_types = set_with(array_types, (char *)t);
- ENDFORSET(fs1);
- N_PTYPES(index_node) = array_types;
- #ifdef TBSN
- if (cdebug2 > 3) TO_ERRFILE('array_types ' + str array_types);
- #endif
- N_PTYPES(expn) = set_union(op_types, array_types);
- break;
- case as_range: /* A frequent error. */
- pass1_error("Invalid use of discrete range in expression",
- "4.4", expn);
- N_PTYPES(expn) = set_new1((char *) symbol_any);
- break;
- default:
- /* TBSL: in SETL have op_name = om: use 0 for now */
- if (op_name == 0) {
- /* usually a previous error; often an invalid selected */
- /* component name. */
- noop_error = TRUE;
- }
- else
- pass1_error("Invalid operator in expression: ", "4.4, 4.5", expn);
- break;
- }
- }
-
- void resolv_attr(Node expn) /*;resolv_attr*/
- {
- Fortup ft1;
- int exists, i, j, notexists, nat, attrkind;
- Symbol s1, s;
- Node entry_node;
- Symbol range_typ;
- Node arg2;
- Node a_node, arg1;
- Symbol type1;
- Node task_node;
- Symbol task, entry_name;
- Set task_types;
- Node index_node;
- static int is_attribute_prefix = FALSE;
-
- a_node = N_AST1(expn);
- arg1 = N_AST2(expn);
- arg2 = N_AST3(expn);
- if (N_KIND(a_node) == as_simple_name) /* no attribute if simple name here*/
- attrkind = ATTR_any;
- else
- attrkind = (int) attribute_kind(expn); /* numeric code for attribute */
-
- /* verify that BASE appears only as the prefix of another attribute */
- if (attrkind == ATTR_BASE && !is_attribute_prefix)
- #ifdef ERRNUM
- errmsgn(236, 233, expn);
- #else
- errmsg("Invalid use of attribute BASE", "Annex A", expn);
- #endif
- is_attribute_prefix = TRUE;
-
- /* First - for attributes applying to objects or types, change
- * attrkind to reflect the type of entity to which the attribute
- * is being applied.
- */
- if ( attrkind == ATTR_FIRST || attrkind == ATTR_LAST
- || attrkind == ATTR_RANGE || attrkind == ATTR_LENGTH
- || attrkind == ATTR_SIZE || attrkind == ATTR_CONSTRAINED)
- attrkind = (int)(attribute_kind(expn) +=(is_type_node(arg1) ? 2:1));
-
- /* We find the type of the left argument of the attribute. */
- /* It may be a type name, in which case there is nothing to be */
- /* done. */
-
- if (is_type_node(arg1)) {
- type1 = N_UNQ(arg1);
- if (is_incomplete_type(type1)) {
- premature_access(type1, arg1);
- N_PTYPES(expn) = set_new1((char *) symbol_any);
- return;
- }
- if (is_task_type(type1)
- &&(attrkind != ATTR_BASE
- && attrkind != ATTR_O_SIZE && attrkind != ATTR_T_SIZE
- && attrkind != ATTR_STORAGE_SIZE)) {
- /* may refer to current task */
- if (in_open_scopes(type1))
- N_UNQ(arg1) = dcl_get(DECLARED(type1), "current_task");
- else
- /* use of the task type otherwise is invalid.*/
- pass1_error("invalid use of task type outside of it own body",
- "9.1", arg1);
- }
- N_PTYPES(arg1) = set_new1((char *) type1);
- }
- else if (attrkind == ATTR_COUNT) {
- find_entry_name(arg1);
- task_node = N_AST1(arg1);
- entry_node = N_AST2(arg1);
- task_types = N_PTYPES(task_node);
-
- if (entry_node == OPT_NODE || set_size(task_types) == 0) {
- /* previous error*/
- noop_error = TRUE;
- return;
- }
-
- if (N_KIND(arg1) == as_entry_family_name) {
- entry_name = N_UNQ(entry_node);
- index_node = N_AST3(arg1);
- range_typ = (Symbol) index_type(TYPE_OF(entry_name));
- check_type(range_typ, index_node);
- N_KIND(arg1) = as_entry_name; /* for common processing */
- }
- else { /* single entry, possibly overloaded */
- if (set_size(N_NAMES(arg1)) > 1) {
- #ifdef ERRNUM
- errmsgn(237, 238, entry_node);
- #else
- errmsg("ambiguous entry name for attribute", "9.9", entry_node);
- #endif
- return;
- }
- else {
- entry_name = (Symbol) set_arb(N_NAMES(arg1));
- N_UNQ(entry_node) = entry_name;
- N_AST3(arg1) = OPT_NODE; /* discard N_NAMES */
- }
- }
- complete_task_name(task_node, TYPE_OF(SCOPE_OF(entry_name)));
- task= N_UNQ(task_node);
-
- /* The COUNT attribute can only be used immediately within*/
- /* the object executing the task body. */
- exists = FALSE;
- if (N_KIND(task_node) != as_simple_name) exists = TRUE;
- if (!exists) {
- /* check that the task is one of the open scopes */
- notexists = TRUE;
- FORTUPI(s = (Symbol), open_scopes, i, ft1);
- s = (Symbol) open_scopes[i];
- if (task == s
- || strcmp(original_name(task), "current_task") == 0
- && SCOPE_OF(task) == s) {
- notexists = FALSE;
- break;
- }
- ENDFORTUP(ft1);
- if (notexists) exists = TRUE; /* not in open scopes */
- }
- if (!exists) {
- /* intervening scopes cannot be subprograms, etc */
- for (j = 1; j <= i-1; j++) {
- s1 = (Symbol) open_scopes[j];
- nat = NATURE(s1);
- if (nat != na_block && nat != na_entry
- && nat != na_entry_family) {
- exists = TRUE;
- break;
- }
- }
- }
- if (exists) {
- pass1_error_l( "E\'COUNT can only be used within the body ",
- "of the task containing E", "9.9", expn);
- return;
- }
-
- type1 = symbol_none;
- N_PTYPES(arg1) = set_new1((char *) symbol_none);
- }
- else {
- resolve1(arg1);
- if (set_size(N_PTYPES(arg1)) != 1) {
- pass1_error_str("Invalid argument for attribute %",
- attribute_str(attrkind), "Annex A, 4.1.4", expn);
- return;
- }
- else
- type1 = (Symbol) set_arb(N_PTYPES(arg1));
- }
-
- is_attribute_prefix = FALSE; /* clear flag */
-
- /* Verify that the type has received a full declaration. */
- if (is_incomplete_type(type1)) {
- /* 'SIZE and 'ADDRESS can be applied to a deffered constant,
- * in the default expression for record components and non-
- * generic formal parameters. The nature of the current scope
- * is either na_record or na_void(formal part or discr. part).
- */
- if (!is_type_node(arg1) &&
- (attrkind == ATTR_O_SIZE || attrkind == ATTR_T_SIZE
- || attrkind == ATTR_ADDRESS) &&(NATURE(scope_name) == na_void
- || NATURE(scope_name) == na_record)) {
- ;
- }
- else {
- premature_access(type1, arg1);
- N_PTYPES(expn) = set_new1((char *) symbol_any);
- return;
- }
- }
- /* Verify that attributes have the proper number of arguments. */
-
- if (is_scalar_type(type1) &&
- ( attrkind == ATTR_O_FIRST || attrkind == ATTR_T_FIRST
- || attrkind == ATTR_O_LAST || attrkind == ATTR_T_LAST)) {
- if (arg2 != OPT_NODE) {
- pass1_error_str("Invalid second argument for attribute %",
- attribute_str(attrkind), "Annex A, 4.1.4", arg2);
- }
- else if ((N_KIND(arg1) == as_simple_name &&(!is_type(N_UNQ(arg1))))
- || (N_KIND(arg1) == as_attribute
- && (int) attribute_kind(arg1) != ATTR_BASE)) {
- pass1_error("attribute cannot be applied to scalar object",
- "Annex A", a_node);
- }
- }
- else if (attrkind == ATTR_POS
- || attrkind == ATTR_VAL
- || attrkind == ATTR_PRED
- || attrkind == ATTR_SUCC
- || attrkind == ATTR_VALUE
- || attrkind == ATTR_IMAGE) {
- if (arg2 == OPT_NODE) {
- pass1_error("Missing second argument for attribute ",
- "Annex A", a_node);
- return;
- }
- else
- if (!is_type_node(arg1) || (N_KIND(arg1) == as_attribute
- && (int) attribute_kind(arg1) == ATTR_BASE)) {
- pass1_error_l("First argument of attribute must ",
- "be a type mark", "Annex A", a_node);
- return;
- }
- }
-
- /* In the case of array attributes, the argument may be an access */
- /* object. Dereference it now. */
- if ((attrkind == ATTR_O_FIRST || attrkind == ATTR_T_FIRST
- || attrkind == ATTR_O_LAST || attrkind == ATTR_T_LAST
- || attrkind == ATTR_O_RANGE || attrkind == ATTR_T_RANGE
- || attrkind == ATTR_O_LENGTH || attrkind == ATTR_T_LENGTH)
- && is_access(type1)
- && is_array((Symbol)(designated_type(type1)))) {
- if (is_fully_private(type1)) {
- premature_access(type1, arg1);
- N_PTYPES(expn) = set_new1((char *)symbol_any);
- return;
- }
- dereference_node(arg1, type1);
- type1 = (Symbol) designated_type(type1);
- }
- else if ((attrkind == ATTR_CALLABLE || attrkind == ATTR_TERMINATED)
- && is_access(type1)) {
- dereference_node(arg1, type1);
- type1 = (Symbol) designated_type(type1);
- }
-
- if (arg2 == OPT_NODE) {
- /* For array attributes, a missing second argument is */
- /* equivalent to a reference to the first dimension. */
- arg2 = node_new(as_int_literal);
- set_span(arg2, get_right_span(N_AST2(expn)));
- N_VAL(arg2) = strjoin("1", "");
- N_AST3(expn) = arg2;
- }
-
- /* The procedure attribute-type will resolve fully arg2 */
- /* in the case of array attributes, to obtain a dimension no. */
-
- N_PTYPES(expn) =
- set_new1((char *)attribute_type(attrkind, type1, arg1, arg2));
- }
-
- /* Made case as_attribute in resolve2 into separate procedure
- * resolve2_attr. Having resolve2_attr return (Symbol)0 in case of pass1_error.
- */
-
- static void dereference_node(Node arg1, Symbol type1) /*;dereference_node*/
- {
- /* the prefix of several attributes must be appropriate for the type,
- * i.e. it can be an access to an entity of the proper kind. This
- * routine is called to emit an explicit dereference (.all) in such cases.
- */
-
- Node acc_arg1;
-
- if (is_type_node(arg1)) {
- ; /* no op */
- }
- else { /* Dereference object */
- acc_arg1 = copy_node(arg1);
- N_AST2(arg1) = (Node)0;
- N_AST3(arg1) = (Node)0;
- N_AST4(arg1) = (Node)0;
- N_PTYPES(acc_arg1) = set_new1((char *)type1);
- N_KIND(arg1) = as_all;
- N_AST1(arg1) = acc_arg1;
- }
- N_PTYPES(arg1) = set_new1((char *)designated_type(type1));
- }
-
- void resolve2(Node expn, Symbol context_typ) /*;resolve2*/
- {
- /* This procedure performs the second, top-down pass of the
- * type validation and overloading resolution.
- * second argument is the type which the expression must yield.
- * If the expression is overloaded, only one of its instances must
- * yield -context_typ-. Once this is ascertained, the known types of the
- *formals for the top level operator in expression, are propagated
- * downwards to the actuals.
- */
-
- Fortup ft1;
- Forset fs1;
- int exists, nat, nk;
- Set types, a_types, ntypes;
- Set oa_types = (Set) 0;
- Symbol name, type2, c, rtype, target_type, ntype_sym;
- Node op_node, args_node, node;
- Set valid_ops;
- Symbol op_name, atysym, t2;
- Set op_names;
- Tuple tup, indices;
- Symbol target_typ;
- Node array1;
- Symbol array_type;
- int out_c;
- Tuple index_list;
- Node index;
- int i, may_others;
- Node discr1, e, ac_expn;
- Symbol access_type;
- Node type_node, expn1, entry_node;
- Symbol alloc_type;
- Symbol accessed_type;
- /*char *chk;*/
- char *strvstr;
- Tuple strvtup;
- int strvlen, strvi;
- Symbol t;
- Symbol c1, c2;
- Set tu;
- Node t_node, constraint, low, high;
- Symbol b_type;
- int kind;
- Node call_node, index_node;
- Const lv; /*TBSL: check type of lv */
- char *orignam;
- Tuple litmaptup;
- int litmapi;
- Span save_span;
-
- if (cdebug2 > 0) {
- TO_ERRFILE("resolve2 ");
- #ifdef IBM_PC
- printf(" %p %s context %p %s\n"
- , expn, kind_str(N_KIND(expn)), context_typ,
- ((context_typ != (Symbol)0)? ORIG_NAME(context_typ):""));
- #else
- printf(" %ld %s context %ld %s\n"
- , expn, kind_str(N_KIND(expn)), context_typ,
- ((context_typ != (Symbol)0)? ORIG_NAME(context_typ):""));
- #endif
- }
- if (context_typ == (Symbol)0)
- printf("??:resolve2 context_typ null\n");
- if (noop_error) return;
-
- types = N_PTYPES(expn);
-
- if (expn == OPT_NODE) return;
-
- switch (nk = N_KIND(expn)) {
- case as_simple_name:
- name = N_UNQ(expn);
- /* If constant, get its value, and if universal constant,
- * convert when necessary.
- */
- type2 = TYPE_OF(name);
- if (!compatible_types(context_typ, type2)) {
- #ifdef ERRNUM
- id_type_errmsgn(239, name, context_typ, 10, expn);
- #else
- errmsg_id_type("% has incorrect type. Expect %", name, context_typ,
- "none", expn);
- #endif
- noop_error = TRUE;
- return;
- }
- else
- if ((NATURE(name) == na_out) &&(!out_context)) {
- #ifdef ERRNUM
- id_errmsgn(240, name, 241, expn);
- #else
- errmsg_id("invalid reading of out parameter %", name, "6.2",
- expn);
- #endif
- }
- if (NATURE(name) == na_constant) {
- if (in_univ_types(type2)) {
- copy_attributes((Node) SIGNATURE(name), expn);
- specialize(expn, context_typ);
- type2 = base_type(context_typ);
- }
- else if ((Node) SIGNATURE(name) == OPT_NODE
- && (NATURE(scope_name) != na_void
- && NATURE(scope_name) != na_record)) {
- /* Only permissible contexts for a defered constant are
- * formal parts and component declarations.
- */
- #ifdef ERRNUM
- l_errmsgn(242, 243, 43, expn);
- #else
- errmsg_l("premature use of deferred constant before its",
- "full declaration", "7.4.3", expn);
- #endif
- }
- }
- else eval_static(expn);
- break;
- case as_character_literal:
- exists = FALSE;
- FORSET(c = (Symbol), N_NAMES(expn), fs1);
- if (compatible_types(context_typ, TYPE_OF(c))) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists) {
- type2 = TYPE_OF(c);
- /*N_VAL(expn) = literal_map(type2)(original_name(c));*/
- /* In the C version, create a Const with this value */
- orignam = ORIG_NAME(c);
- if (orignam == (char *)0) chaos("resolve2 null literal");
- litmaptup = (Tuple) literal_map(type2);
- for (litmapi = 1; litmapi <= tup_size(litmaptup); litmapi += 2) {
- if (streq(orignam, litmaptup[litmapi])) {
- N_VAL(expn) = (char *) int_const((int)litmaptup[litmapi+1]);
- break;
- }
- }
- }
- else {
- char *tmp_msg;
-
- tmp_msg = strjoin(N_VAL(expn), " has incorrect type. Expect %");
- #ifdef ERRNUM
- type1_errmsgn(tmp_msg, context_typ, 10, expn);
- #else
- errmsg_type(tmp_msg, context_typ, "none", expn);
- #endif
- type2 = symbol_any;
- N_VAL(expn) = (char *) int_const(0);
- }
- N_KIND(expn) = as_ivalue;
- N_OVERLOADED(expn) = FALSE;
- N_PTYPES(expn) = (Set) 0;
- N_NAMES(expn) = (Set) 0;
- break;
- case as_op:
- case as_un_op:
- case as_call:
- op_node = N_AST1(expn);
- args_node = N_AST2(expn);
- op_names = N_NAMES(op_node);
-
- /* Find instance of operator that yields type imposed by context. */
- valid_ops = set_new(0);
- FORSET(name = (Symbol), op_names, fs1);
- if (compatible_types(context_typ, TYPE_OF(name)))
- valid_ops = set_with(valid_ops, (char *) name);
- ENDFORSET(fs1);
-
- N_NAMES(op_node) = valid_ops;
-
- if (set_size(valid_ops) > 1)
- disambiguate(expn, context_typ);
-
- if (set_size(N_NAMES(op_node)) > 1)
- /* try removing implicit conversions of universal quantities. */
- remove_conversions(expn);
-
- /* Now there should be only one possiblity left. */
- valid_ops = N_NAMES(op_node);
- if (set_size(valid_ops) != 1) {
- if (cdebug2 > 2) {
- #ifdef TBSN
- ??(for nam in valid_ops)
- TO_ERRFILE('OVERLOADS ', nam, SYMBTAB(nam));
- end for;
- #endif
- }
- type_error(op_names, context_typ, set_size(valid_ops), op_node);
- return;
- }
- else {
- op_name = (Symbol) set_arb(valid_ops);
- type2 = TYPE_OF(op_name);
- }
-
- N_OVERLOADED(expn) = FALSE; /* DS -check this */
- N_NAMES(expn) = N_PTYPES(expn) = (Set)0;
- /* For a predefined operator, the type imposed by context fixes
- * the types of the arguments. The signature of a predefined op.
- * contains only classes of types, and it ignored in this pass.
- * The resulting type must be that of the context.
- */
- switch (nat = NATURE(op_name)) {
- case na_op:
- type2 = base_type(context_typ);
- N_UNQ(op_node) = op_name;
- complete_op_expr(expn, type2);
- /* The expression "+"(1, 2) is syntactically a function call. At
- * this point it recognized as an operator node.
- */
- if (N_KIND(expn) == as_call)
- N_KIND(expn) = (tup_size(N_LIST(args_node)) == 1) ? as_un_op
- : as_op;
-
- /* For a procedure or function, the signature imposes a type on
- * each actual parameter present, and specifies a default value
- * for the ones that are absent. If the function is aliased(ie
- * a renaming or derivation) the parent subprogram is called.
- */
- break;
- case na_procedure:
- case na_procedure_spec:
- case na_function:
- case na_function_spec:
- complete_arg_list(SIGNATURE(op_name), args_node);
- N_KIND(expn) = as_call;
- N_UNQ(op_node) = op_name;
- TO_XREF(op_name);
- break;
- case na_entry:
- case na_entry_family:
- complete_arg_list(SIGNATURE(op_name), args_node);
- N_KIND(expn) = as_ecall;
- if (N_KIND(op_node) == as_entry_name
- || N_KIND(op_node) == as_entry_family_name) {
- entry_node = N_AST2(op_node);
- /* Note the unique name on the entry name node. */
- N_UNQ(entry_node) = op_name;
- }
- else { /* called from proc_or_entry, no entry name yet */
- N_UNQ(op_node) = op_name;
- }
- TO_XREF(op_name);
-
- /* Resolved enumeration literals are returned as themselves. */
- break;
- case na_literal:
- save_span = get_left_span(expn);
- N_KIND(expn) = as_simple_name;
- N_UNQ(expn) = op_name;
- set_span(expn, save_span);
- N_AST2(expn) = (Node)0; /* clear ast */
- N_VAL(expn) = ORIG_NAME(op_name);
- TO_XREF(op_name);
- break;
- }
- /* Remaining cases are basic operations. */
- break;
- case as_int_literal:
- /* If the context type is not universal, the literal must be trans-
- * formed to its short SETL form.
- */
- target_typ = ((context_typ == symbol_universal_integer)
- ? symbol_universal_integer : symbol_integer);
-
- lv = adaval(target_typ, N_VAL(expn));
- if (adaval_overflow)
- create_raise(expn, symbol_numeric_error);
- else {
- ast_clear(expn);
- N_KIND(expn) = as_ivalue;
- N_VAL(expn) = (char *) lv;
- }
- type2 = base_type(context_typ); /* inherited from context */
- if (root_type(type2) != symbol_integer
- && root_type(type2) != symbol_universal_integer) {
- #ifdef ERRNUM
- errmsgn(244, 245, expn);
- #else
- errmsg("invalid context for integer literal", "4.6(15)", expn);
- #endif
- }
- break;
- case as_real_literal:
- /* If the context is not universal, or is not a fixed type, then
- * convert the literal to a SETL floating number.
- */
- target_typ = (context_typ == symbol_universal_real
- || is_fixed_type(root_type(context_typ)))
- ? symbol_universal_real: symbol_float;
- lv = adaval(target_typ, N_VAL(expn));
- if (adaval_overflow)
- create_raise(expn, symbol_constraint_error);
- else {
- ast_clear(expn);
- N_KIND(expn) = as_ivalue;
- N_VAL(expn) = (char *) lv;
- }
- type2 = base_type(context_typ); /* inherited from context */
- if (root_type(type2) != symbol_float
- && !is_fixed_type(root_type(type2))
- && root_type(type2) != symbol_universal_real) {
- #ifdef ERRNUM
- errmsgn(246, 245, expn);
- #else
- errmsg("invalid context for real literal", "4.6(15)", expn);
- #endif
- }
- break;
- case as_string_literal:
- if (is_array(context_typ)) {
- if (context_typ == symbol_string_type) {
- /* verify that only one string type is visible. */
- context_typ = symbol_string;
- }
- else if (is_fully_private(context_typ))
- premature_access(context_typ, expn);
-
- if (root_type(context_typ) == symbol_string) {
- /*N_VAL(expn) := [abs c: c in N_VAL(expn)];*/
- strvstr = N_VAL(expn);
- strvlen = strlen(strvstr);
- strvtup = tup_new(strvlen);
- for (strvi = 1; strvi <= strvlen; strvi++)
- strvtup[strvi] = (char *) strvstr[strvi-1];
- ast_clear(expn);
- N_VAL(expn) = (char *) strvtup;
- N_KIND(expn) = as_string_ivalue;
- N_NAMES(expn) = (Set) 0;
- }
- else {
- /* Context is user-defined array of a character type. */
- complete_string_literal(expn, component_type(context_typ));
- }
- }
- else {
- #ifdef ERRNUM
- type_errmsgn(247, context_typ, 10, expn);
- #else
- errmsg_type("Incorrect type for string literal. Expect %",
- context_typ, "none", expn);
- #endif
- }
- type2 = context_typ;
- break;
- case as_null:
- if (is_access(context_typ)) type2 = context_typ;
- else {
- #ifdef ERRNUM
- errmsgn(248, 249, expn);
- #else
- errmsg("Invalid context for NULL", "3.8.2", expn);
- #endif
- return;
- }
- break;
- case as_aggregate:
- /* Resolve it using the context type, and apply constraint if any.
- * The possible types include all visible composite types, and there
- * should be one of them compatible with the context.
- */
- exists = FALSE;
- FORSET(t = (Symbol), types, fs1);
- if (compatible_types(t, context_typ)) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (!exists) {
- #ifdef ERRNUM
- id_errmsgn(250, context_typ, 251, expn);
- #else
- errmsg_id("No aggregate available for type %", context_typ, "4.2",
- expn);
- #endif
- return;
- }
- else complete_aggregate(context_typ, expn);
-
- type2 = context_typ;
-
- /* in the absence of more precise checks, the type of the
- * aggregate can only be set to the base type (see end of resolve2
- */
- context_typ = base_type (context_typ);
-
- /* For arrays, obtain required index type from type of array
- * expression, and complete the determination of both.
- */
- break;
- case as_index:
- array1 = N_AST1(expn);
- index_node = N_AST2(expn);
-
- array_type = complete_array_expn(expn, context_typ);
-
- /* Previous error*/
- if (array_type == symbol_any) return;
- /* Complete resolution of each index.
- * The index expression is a context in which out parameters
- * cannot be read. This has to be special-cased because an
- * indexed expression on the lhs of an assignment is a valid
- * context for an out parameter, and the global flag out_context
- * is set accordingly in processing assignments.
- */
- out_c = out_context;
- out_context = FALSE;
- index_list = N_LIST(index_node);
-
- FORTUPI(index = (Node), index_list, i, ft1);
- resolve2(index, (Symbol) (index_types(array_type))[i]);
- ENDFORTUP(ft1);
- out_context = out_c;
-
- type2 = (Symbol) component_type(array_type);
- break;
- /* For slices, obtain array type, and apply its index type to the
- * subtype expression for the discrete range.
- */
- case as_slice:
- array1 = N_AST1(expn);
- index_node = N_AST2(expn);
- array_type = complete_array_expn(expn, context_typ);
- /* Previous error*/
- if (array_type == symbol_any)
- return;
- tup = N_LIST(index_node);
- discr1 = (Node) (tup[1]);
- resolve2(discr1, (Symbol) index_type(array_type));
- /* Replace index list with its sole element. */
- N_AST2(expn) = discr1;
- N_AST3(expn) = N_AST4(expn) = (Node) 0;
- type2 = base_type(array_type);
- break;
- case as_selector:
- type2 = complete_selected_expn(expn, context_typ);
-
- /* For a parenthesised expression, resolve the expression, and keep
- * the parenthesis, to distinguish them from variables. The possible
- * constraint of the context is not propagated to the expression.
- * If the context is universal, discard the parenthesis, to enable
- * full evaluation of universal expressions.
- */
- break;
- case as_parenthesis:
- e = N_AST1(expn);
- resolve2(e, base_type(context_typ));
- if (in_univ_types(context_typ))
- copy_attributes(e, expn);
- apply_constraint(e, context_typ);
- type2 = context_typ;
- break;
- /* For a dereference operation, we must verify that the access
- * object points to the right type.
- */
- case as_all:
- ac_expn = N_AST1(expn);
- {
- Symbol t;
-
- a_types = set_new(0);
- FORSET(t = (Symbol), N_PTYPES(ac_expn), fs1);
- if (is_access(t)
- && compatible_types(context_typ, designated_type(t)))
- a_types = set_with(a_types, (char *) t);
- ENDFORSET(fs1);
- }
- /* TBSL: check that t is defined in type_error call dsd 18 aug */
- if (set_size(a_types) != 1) {
- remove_conversions(ac_expn); /* last chance */
- oa_types = a_types;
- a_types = set_new(0);
- FORSET(atysym = (Symbol), N_PTYPES(ac_expn), fs1);
- if (set_mem((char *)atysym, oa_types))
- a_types = set_with(a_types, (char *) atysym);
- ENDFORSET(fs1);
- if (set_size(a_types) != 1) {
- #ifdef TBSL
- ] type_error(set_new1('@'), t, set_size(a_types), expn);
- #endif
- set_free(oa_types);
- set_free(a_types);
- return;
- }
- }
- access_type = (Symbol) set_arb(a_types); /* Only one type left. */
- set_free(a_types);
- if (oa_types != (Set)0)
- set_free(oa_types);
-
- /* We know already that the nature of access type is na_access. */
- type2 = (Symbol) designated_type(access_type);
- /* It is always illegal to dereference an out parameter.*/
- out_c = out_context;
- out_context = FALSE;
- resolve2(ac_expn, access_type);
- out_context = out_c;
- break;
- /* For an allocator, we obtain the type of the access object
- * by dereferencing the access type. The final expression however
- * gives the access type, together with the validated access object.
- */
- case as_new:
- type_node = N_AST1(expn);
- expn1 = N_AST2(expn);
- alloc_type = N_UNQ(type_node);
-
- if (!is_access(context_typ)) {
- #ifdef ERRNUM
- errmsgn(252, 253, expn);
- #else
- errmsg("Context of allocator must be an access type", "4.8, 3.8",
- expn);
- #endif
- return;
- }
-
- accessed_type = (Symbol) designated_type(context_typ);
- /* Verify that the allocator matches the context.
- * The(possibly unconstrained) access type is the one given by the
- * context(eg. declaration). If the allocator provides a constraint
- * rather than an aggregate, then a subtype has been created, and the
- * access type is an access to this constrained type. The constraint
- * must then be emitted so that it is evaluated at the proper time.
- *(The subtype is not an anonymous type, and is introduced only to
- * simplify type checking).
- * The converse may also occur: the context is constrained, but the
- * allocator type is unconstrained. In that case, use the context
- * context type as the type of the expression.
- * Finally, the context may be an unconstrained array type, whose
- * index type is nevertheless bounded. When the allocator is
- * initialized with an aggregate, the bounds of the aggregate must be
- * compatible with that index type.
- */
- if (!compatible_types(accessed_type, alloc_type)) {
- #ifdef ERRNUM
- type_errmsgn(254, accessed_type, 255, type_node);
- #else
- errmsg_type("Invalid type for allocator. Expect %", accessed_type,
- "3.8, 4.8", type_node);
- #endif
- return;
- }
-
- if (expn1 != OPT_NODE) {
- res2_check(expn1, alloc_type);
- if (is_array(accessed_type) && can_constrain(accessed_type)) {
- /* bounds of the aggregate will have to be shown to be
- * compatible with the (unconstrained) designated type.
- */
- make_constrained_node(expn1, accessed_type, as_qual_sub);
- }
- else if (!can_constrain(accessed_type)
- && accessed_type != alloc_type) {
- /*A further qualification is necessary.*/
- may_others = full_others;
- full_others = TRUE;
- apply_constraint(expn1, accessed_type);
- full_others = may_others;
- }
- }
- else if (is_array(alloc_type) && N_KIND(type_node) == as_subtype_decl) {
- /* the index subtypes of the type will have to be elaborated. */
- indices = tup_new(0);
- {
- Symbol i;
- FORTUP(i = (Symbol), index_types(alloc_type), ft1);
- indices =
- tup_with(indices, (char *) new_subtype_decl_node(i));
- ENDFORTUP(ft1);
- }
- N_TYPE(expn) = context_typ;
- make_insert_node(expn, indices, copy_node(expn));
- }
-
- else if (is_access(alloc_type) && N_KIND(type_node) == as_subtype_decl){
- /* the designated type is anonymous, and will also be elaborated. */
- indices = tup_new(0);
- {
- Symbol i, d;
- d = (Symbol) designated_type(alloc_type);
- if is_array(d) { /* elaborate indices as well */
- FORTUP(i = (Symbol), index_types(d), ft1);
- indices =
- tup_with(indices, (char *) new_subtype_decl_node(i));
- ENDFORTUP(ft1);
- }
- indices = tup_with(indices, (char *) new_subtype_decl_node(d));
- }
- N_TYPE(expn) = context_typ;
- make_insert_node(expn, indices, copy_node(expn));
- }
- type2 = context_typ;/* No further constraints */
- break;
- /* For an attribute, we complete the type checking of the right
- * argument, and if it must be a static expression, we perform
- * the appropriate check and extract the attribute.
- */
- case as_attribute:
- case as_range_attribute:
- type2 = resolve2_attr(expn, context_typ);
- /* return immediately if resolve_attr failed due to pass1_error */
- if (type2== (Symbol)0) return;
- break;
- /* A conversion may imply a run-time action, or may be used
- * between types of the same structure to achieve type consistency.
- * In the later case, do not emit any conversion.
- * In both cases however, a range check may be needed.
- */
-
- case as_convert:
- t_node = N_AST1(expn);
- expn1 = N_AST2(expn);
- target_type = N_UNQ(t_node);
- type2 = target_type;
- types = N_PTYPES(expn1);
- /* Apply the preference rule to choose a universal meaning for
- * the expression in case of overloading of operators.
- */
- /*tu = set_inter(types, univ_types);*/
- tu = set_new(0);
- if (set_mem((char *) symbol_universal_integer, types))
- tu = set_with(tu, (char *) symbol_universal_integer);
- if (set_mem((char *) symbol_universal_real, types))
- tu = set_with(tu, (char *) symbol_universal_real);
- if (set_size(types) > 1 && set_size(tu) == 1)
- types = tu;
- else set_free(tu);
-
- /* Verify that original expression is unambiguous. */
- if (set_size(types) != 1) {
- #ifdef ERRNUM
- errmsgn(256, 257, expn1);
- #else
- errmsg("ambiguous expression for conversion", "4.6", expn1);
- #endif
- return;
- }
- else {
- t = (Symbol) set_arb(types);
- /* resolve2(expn1, t); */
- if (is_numeric(t) && is_numeric(target_type)) {
- /* conversions between any two numeric types are allowed. */
- /* all done */
-
- resolve2 (expn1, t);
- N_AST2 (expn) = expn1;
- /* N_AST1 (expn) = new_name_node (t); */
- N_TYPE (expn) = target_type;
- }
- /* conversion of records with discriminant will be valid if
- * the discriminants have the same values
- */
- else if (is_record (target_type) && has_discriminants (target_type)
- && (root_type (target_type) == root_type (t))) {
- resolve2 (expn1, t);
- N_KIND (expn) = as_qual_discr;
- N_AST1 (expn) = expn1;
- N_AST2 (expn) = (Node) 0;
- N_TYPE (expn) = target_type;
- }
- /* conversion of access values pointing to arrays will be valid
- * if the indexes of the designated type have the same values
- */
-
- else if (is_access (target_type)
- && is_array (designated_type(target_type))
- && (root_type (target_type) == root_type (t))) {
- resolve2 (expn1, t);
- N_KIND (expn) = as_qual_aindex;
- N_AST1 (expn) = expn1;
- N_AST2 (expn) = (Node) 0;
- N_TYPE (expn) = target_type;
- }
- /* conversion of access values pointing to records with discriminant
- * will be valid if the discriminants of the designated type have
- * the same values
- */
-
- else if (is_access (target_type)
- && is_record (designated_type(target_type))
- && has_discriminants (designated_type(target_type))
- && (root_type (target_type) == root_type (t))) {
- resolve2 (expn1, t);
- N_KIND (expn) = as_qual_adiscr;
- N_AST1 (expn) = expn1;
- N_AST2 (expn) = (Node) 0;
- N_TYPE (expn) = target_type;
- }
-
- else if (root_type(target_type) == root_type(t)) {
- /* conversions among types derived from a common root. In
- * the absence of representation specifications, this is a
- * noop, indicated here by having the same type on both sides
- */
- resolve2 (expn1, t);
- N_AST2 (expn) = expn1;
- /* N_AST1 (expn) = new_name_node (t); */
- N_TYPE (expn) = target_type;
- }
- else if (is_array(target_type)) {
- /* conversion between array types are allowed, if types of
- * indices are convertible and component types are the same.
- */
- exists = FALSE;
- if ( is_array(t)
- && no_dimensions(t) == no_dimensions(target_type))
- exists = TRUE;
- if (exists) {
- for (i = 1; i <= no_dimensions(t); i++) {
- if (root_type((Symbol)index_types(target_type)[i])
- != root_type((Symbol)index_types(t)[i])) {
- exists = FALSE;
- break;
- }
- }
- }
- if (exists) {
- if ( base_type((Symbol)component_type(target_type))
- != base_type((Symbol) component_type(t)))
- exists = FALSE;
- }
- if (exists) { /* convertible */
- /* the following lines have been translated from the Setl
- * version
- */
-
- if (is_access (component_type (t))) {
- c1 = designated_type (component_type (t));
- c2 = designated_type (component_type (target_type));
- }
- else {
- c1 = component_type (t);
- c2 = component_type (target_type);
- }
- if ((can_constrain (c1)) != (can_constrain (c2))) {
- #ifdef ERRNUM
- l_errmsgn(480, 481, 482, expn);
- #else
- errmsg_l ("component types in array conversion must",
- " be both constrained or unconstrained",
- "4.6 (11)", expn);
- #endif
- return;
- }
- resolve2 (expn1, t);
- N_AST2 (expn) = expn1;
- N_TYPE (expn) = target_type;
-
- check_array_conversion(expn, t, target_type);
- }
- else {
- #ifdef ERRNUM
- errmsgn(258, 257, expn);
- #else
- errmsg("Invalid array conversion", "4.6", expn);
- #endif
- return;
- }
- }
- else {
- #ifdef ERRNUM
- id_errmsgn(259, target_type, 257, expn);
- #else
- errmsg_id("cannot convert to %", target_type, "4.6", expn);
- #endif
- }
- }
- /* if (N_KIND(expn) == as_insert) expn = N_AST1(expn);
- * N_TYPE(expn) = base_type(type2);
- * the result of the conversion must belong to the target subtype.
- * if (!is_array(t)) {
- * apply_constraint(expn, type2);
- */
-
- apply_constraint (expn, target_type);
- break;
- case as_qualify:
-
- /* proc resolve2_qualify(expn, context_type);
- * sem_trace3(3, 'At proc resolve2_qualify ', expn);
- * [-, to_type, expn1] := expn;
- * $ No sliding for aggregates here.
- * may_others := full_others;
- * full_others := true;
- * expn2 := eval_static(apply_constraint(resolve2(expn1, to_type),
- * to_type));
- * full_others := may_others;
- * return [['qualify', expn2], to_type];
- */
- t_node = N_AST1(expn);
- expn1 = N_AST2(expn);
- type2 = N_UNQ(t_node);
-
- /* This is non-sliding context for aggregates. */
- may_others = full_others;
- full_others = TRUE;
- resolve2(expn1, type2);
- eval_static(expn1);
-
- apply_constraint(expn1, type2); /* impose checks. */
-
- full_others = may_others;
- break;
- /* For a subtype, complete the evaluation of the bounds.
- * If the bounds are literal, the type may be a universal one.
- * replace it now by the corresponding non-literal type.
- */
- case as_subtype:
- type_node = N_AST1(expn);
- constraint = N_AST2(expn);
- low = N_AST1(constraint);
- high = N_AST2(constraint);
- /* If the bounds are overloaded, the subtype itself may be an
- * overloaded expression. Extract the type(s) that are compatible
- * with context .
- */
- ntypes = set_new(0);
- FORSET(ntype_sym = (Symbol), types, fs1);
- if (compatible_types(context_typ, ntype_sym))
- ntypes = set_with(ntypes, (char *) ntype_sym);
- ENDFORSET(fs1);
- set_free(types);
- types = ntypes;
- /* Make sure that only one type is possible. */
- if (set_size(types) > 1) {
- /*types = set_diff(types, univ_types);*/
- ntypes = set_new(0);
- FORSET(ntype_sym = (Symbol), types, fs1);
- if (ntype_sym != symbol_universal_integer
- && ntype_sym != symbol_universal_real)
- ntypes = set_with(ntypes, (char *) ntype_sym);
- ENDFORSET(fs1);
- set_free(types);
- types = ntypes;
- }
- if (set_size(types) != 1) {
- type_error(set_new1((char *)symbol_any), context_typ,
- set_size(types), expn);
- N_TYPE(expn) = symbol_any;
- return;
- }
- else
- b_type = base_type((Symbol)set_arb(types));
-
- /* In the case of a range in a membership op, the type may be a real
- * one, in which case the precision is inherited from the context .
- */
- rtype = root_type(context_typ);
-
- if (rtype == symbol_float || rtype == symbol_universal_real)
- kind = as_digits;
- else if (is_fixed_type(rtype))
- kind = as_delta;
- else
- kind = as_range;/* $ Discrete type. */
-
- if (type_node != OPT_NODE)
- b_type = N_UNQ(type_node);
- else {
- if (kind == as_range) {
- if (b_type == symbol_universal_integer) {
- b_type = symbol_integer;
- if (context_typ == symbol_universal_integer
- && (N_KIND(low) == as_op
- || N_KIND(low) == as_un_op
- || N_KIND(high) == as_op
- || N_KIND(high) == as_un_op)) {
- /* i.e. discrete range in arr def. or iteration rule.*/
- /* Not a literal, named number, or attribute(3.6.1(2))*/
- #ifdef ERRNUM
- l_errmsgn(260, 261, 195, expn);
- #else
- errmsg_l("Invalid universal expression in",
- " discrete range", "3.6.1", expn);
- #endif
- N_TYPE(expn) = symbol_any;
- return;
- }
- }
- }
- else if (kind == as_delta)
- b_type = context_typ;
- else if (kind == as_digits)
- b_type = symbol_float;
- }
- /* If the type name was not specified, then it is the type
- * of the bounds.
- */
- if (type_node == OPT_NODE) {
- type_node = node_new(as_simple_name);
- copy_span(constraint, type_node);
- N_UNQ(type_node) = b_type;
- N_AST1(expn) = type_node;
- N_AST2(expn) = constraint;
- if (N_AST3_DEFINED(N_KIND(expn))) N_AST3(expn) = (Node)0;
- if (N_AST4_DEFINED(N_KIND(expn))) N_AST4(expn) = (Node)0;
- }
- resolve2(low, b_type);
- resolve2(high, b_type);
- /* An index constraint may depend on a discriminant . Verify that
- * if a discriminant appears, it is by itself, and not as part of
- * a larger expression.
- */
- check_discriminant(low);
- check_discriminant(high);
- eval_static(low);
- eval_static(high);
- if (is_discrete_type(b_type)) check_bounds_in_range(low, high, b_type);
-
- /* No constraint is imposed on the subtype node itself.*/
- type2 = b_type;
- context_typ = b_type;
- break;
- case as_call_or_index:
- /* Find the tree which has a type compatible with the context, and
- * resolve it.
- */
- call_node = N_AST1(expn);
- index_node = N_AST2(expn);
- exists = FALSE;
- FORSET(t = (Symbol), N_PTYPES(call_node), fs1);
- if (compatible_types(t, context_typ)) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists) {
- node = call_node;
- exists = FALSE;
- FORSET(t2 = (Symbol), N_PTYPES(index_node), fs1);
- if( compatible_types(t2, context_typ)) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists) {
- remove_conversions(call_node); /* last chance */
- remove_conversions(index_node);
- exists = FALSE;
- FORSET(t = (Symbol), N_PTYPES(call_node), fs1);
- if ( compatible_types(t, context_typ)) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists) {
- node = call_node;
- exists = FALSE;
- FORSET(t2 = (Symbol), N_PTYPES(index_node), fs1);
- if (compatible_types(t2, context_typ)) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists) {
- #ifdef TBSL
- type_error(set_new1('call or index'), context_typ, 2,
- expn);
- #endif
- }
- }
- else node = index_node;
- }
- }
- else node = index_node;
- resolve2(node, context_typ);
- copy_attributes(node, expn);
- type2 = N_TYPE(node);
- break;
- default:
- /* Other operators require no propagation */
- type2 = (Symbol) set_arb(types);
- break;
- }
-
- if (compatible_types(context_typ, type2)) N_TYPE(expn) = type2;
- else {
- #ifdef ERRNUM
- type_errmsgn(262, context_typ, 10, expn);
- #else
- errmsg_type("Incorrect type for expression. Expect %", context_typ,
- "none", expn);
- #endif
- }
- }
-
- static Symbol resolve2_attr(Node expn, Symbol context_typ) /*;resolve2_attr*/
- {
- Forset fs1;
- Set types;
- int attrkind, dim, out_c;
- Symbol type2;
- Const con;
- Node attr_node, arg1, arg2;
- Set types1, types2;
- Symbol type1, t2, itype1;
-
- types = N_PTYPES(expn);
- attr_node = N_AST1(expn);
- arg1 = N_AST2(expn);
- arg2 = N_AST3(expn);
- /* The type of the right argument is determined by the attribute,
- * and has already been evaluated in the case of array attributes.
- */
- /*attribute = N_VAL(attr_node); -- should be dead ds 3-13-86*/
- attrkind = (int) attribute_kind(expn);
- types1 = N_PTYPES(arg1);
- types2 = N_PTYPES(arg2);
- type1 = (Symbol) set_arb(types1);
-
- if (attrkind == ATTR_PRED
- ||attrkind == ATTR_SUCC
- ||attrkind == ATTR_POS
- ||attrkind == ATTR_IMAGE)
- t2 = base_type(type1);
- else if (attrkind == ATTR_VALUE)
- t2 = symbol_string;
- else if (attrkind == ATTR_VAL) {
- Symbol t;
- Set otypes2;
- otypes2 = types2;
- types2 = set_new(0);
- FORSET(t = (Symbol), otypes2, fs1);
- if (compatible_types(t, symbol_integer_type))
- types2 = set_with(types2, (char *) t);
- ENDFORSET(fs1);
- if (set_size(types2) == 0) {
- #ifdef ERRNUM
- errmsgn(263, 233, arg2);
- #else
- errmsg("Second argument of VAL must be of some integer type",
- "Annex A", arg2);
- #endif
- return (Symbol)0;
- }
- else if (set_size(types2) == 1)
- t2 = (Symbol) set_arb(types2);
- else if (set_mem((char *) symbol_universal_integer, types2))
- t2 = symbol_universal_integer;
- else {
- #ifdef ERRNUM
- errmsgn(264, 233, arg2);
- #else
- errmsg("ambiguous argument for attribute VAL", "Annex A", arg2);
- #endif
- return (Symbol)0;
- }
- }
- else
- t2 = symbol_integer;
-
- if (attrkind != ATTR_O_FIRST && attrkind != ATTR_T_FIRST
- && attrkind != ATTR_O_LAST && attrkind != ATTR_T_LAST
- && attrkind != ATTR_O_RANGE && attrkind != ATTR_T_RANGE
- && attrkind != ATTR_O_LENGTH && attrkind != ATTR_T_LENGTH)
- resolve2(arg2, t2);
- if (t2 == symbol_universal_integer) /* possible for VAL */
- specialize(arg2, symbol_integer);
- if ((attrkind == ATTR_POSITION || attrkind == ATTR_FIRST_BIT
- || attrkind == ATTR_LAST_BIT) && N_KIND(arg1) != as_selector) {
- #ifdef ERRNUM
- errmsgn(265, 266, arg1);
- #else
- errmsg("attribute must apply to selected component", "13.7.2", arg1);
- #endif
- }
- /*
- * If the left argument is a type, or if it is a constrained
- * object, then evaluate the attribute on the type, statically if
- * possible.
- */
- /*
- * All attributes, except those that are functions, can be applied
- * to an out parameter, because they do not require reading of the
- * object, or read only its bounds. On the other hand, if the pre-
- * fix is an access type, it cannot be an an out parameter (4.1(4)).
- */
- out_c = out_context; /* Save current setting*/
- out_context = !reads_prefix(attrkind, type1);
- itype1 = type1;
-
- if (is_array(type1)
- && (attrkind == ATTR_O_FIRST || attrkind == ATTR_T_FIRST
- || attrkind == ATTR_O_LAST || attrkind == ATTR_T_LAST
- || attrkind == ATTR_O_RANGE || attrkind == ATTR_T_RANGE
- || attrkind == ATTR_O_LENGTH || attrkind == ATTR_T_LENGTH)) {
- /* The second argument indicates the dimension whose attribute
- * is sought. It must be a static integer(this has been checked
- * already).
- */
- if (!is_static_expr(arg2))
- dim = 1; /* By default. */
- else {
- con = (Const) N_VAL(arg2);
- dim = con->const_value.const_int;
- }
- itype1 = (Symbol) (index_types(type1)[dim]);
- }
-
- if (is_type_node(arg1)) {
- /* This might cause problems in eval_static. */
- /* In at least some cases, N_PTYPES has been set (cf. 4a.c line 1009),
- * so here we clear N_PTYPES lest it be mistaken for N_TYPE (DS 9-18-86)
- */
- N_PTYPES(arg1) = (Set) 0;
- N_UNQ(arg1) = itype1;
- }
- else if (attrkind == ATTR_COUNT) {
- /* entry name is fully resolved in first pass. */
- ; /* no op */
- }
- else {
- resolve2(arg1, type1);
- }
- out_context = out_c; /* restore */
-
- if (in_univ_attributes(attrkind)) {
- if (is_static_expr(expn)) {
- /* Specialize value if context is not universal.*/
- eval_static(expn);
- specialize(expn, context_typ);
- }
- /* in nay case indicate desired context type for subsequent conversion*/
- type2 = base_type(context_typ);
- }
- else { /*$$$ TBSL: check for FIRST_BIT, LAST_BIT*/
- type2 = (Symbol) set_arb(types);
- }
- return type2;
- }
-
- static int in_univ_attributes(int attrkind) /*;in_univ_attributes*/
- {
- /* test if type of attribute is universal type */
- static int attrs[] = {
- ATTR_AFT, ATTR_COUNT, ATTR_DIGITS, ATTR_EMAX, ATTR_FIRST_BIT, ATTR_FORE,
- ATTR_LAST_BIT, ATTR_O_LENGTH, ATTR_T_LENGTH, ATTR_MACHINE_EMAX,
- ATTR_MACHINE_EMIN, ATTR_MACHINE_MANTISSA, ATTR_MACHINE_RADIX,
- ATTR_MANTISSA, ATTR_POS, ATTR_POSITION, ATTR_SAFE_EMAX, ATTR_O_SIZE,
- ATTR_T_SIZE, ATTR_STORAGE_SIZE, ATTR_WIDTH, ATTR_DELTA, ATTR_EPSILON,
- ATTR_LARGE, ATTR_SMALL, ATTR_SAFE_LARGE, ATTR_SAFE_SMALL,
- ATTR_O_CONSTRAINED, ATTR_T_CONSTRAINED, ATTR_MACHINE_OVERFLOWS,
- ATTR_MACHINE_ROUNDS, ATTR_CALLABLE, ATTR_TERMINATED, 999 };
- int i;
- for (i = 0; ; i++) {
- if (attrs[i] == 999) return FALSE;
- if (attrs[i] == attrkind) return TRUE;
- }
- }
-
- static void check_bounds_in_range(Node low, Node high, Symbol b_type)
- /*;check_bounds_in_range*/
- {
- /* check if the bounds of an array with a subtype_declaration are
- * in the bounds of the base_type, when static. (When not static,
- * a qual_range is introduced on as_convert).
- */
-
- Node lbd_range, ubd_range;
- int low_val, high_val, lbd_val, ubd_val;
- Tuple b_range_tup;
- Const low_const, high_const, lbd_const, ubd_const;
-
- b_range_tup = SIGNATURE(b_type);
- lbd_range = (Node) b_range_tup[2];
- ubd_range = (Node) b_range_tup[3];
- if (N_KIND(low) == as_qualify) low = N_AST2(low);
- if (N_KIND(high) == as_qualify) high = N_AST2(high);
-
- if (is_static_expr(low) && is_static_expr(high)
- && is_static_expr(lbd_range) && is_static_expr(ubd_range)) {
- low_const = (Const) N_VAL(low);
- high_const = (Const) N_VAL(high);
- lbd_const = (Const) N_VAL(lbd_range);
- ubd_const = (Const) N_VAL(ubd_range);
- const_check(low_const, CONST_INT);
- const_check(high_const, CONST_INT);
- const_check(lbd_const, CONST_INT);
- const_check(ubd_const, CONST_INT);
- low_val = INTV(low_const);
- high_val = INTV(high_const);
- lbd_val = INTV(lbd_const);
- ubd_val = INTV(ubd_const);
-
- if ((lbd_val > ubd_val && low_val <= high_val)
- || ((low_val <= high_val) && (low_val < lbd_val || low_val > ubd_val
- || high_val > ubd_val || high_val < lbd_val))) {
- create_raise(low, symbol_constraint_error);
- return;
- }
- }
- }
-
- static void check_array_conversion(Node expn, Symbol from_t, Symbol to_t)
- /*;check_array_conversion */
- {
- /* verify that in an array conversion, source and target component types
- * have the same constraints.
- */
-
- Symbol from_c, to_c;
- Tuple checks;
- Tuple from_i, to_i;
- int i;
-
- checks = tup_new(0);
-
- from_c = component_type(from_t);
- to_c = component_type(to_t);
-
- while (is_access (from_c)) {
- from_c = designated_type (from_c);
- to_c = designated_type (to_c);
- }
-
- if (from_c == to_c) {
- ;
- }
- else if (is_scalar_type(from_c))
- checks = tup_with(checks, (char *) new_check_bounds_node(from_c, to_c));
- else if (is_record (from_c) && has_discriminants (from_c))
- checks = new_check_disc_node (from_c, to_c);
- else if (is_array(from_c)) {
- /* index subtypes must be equal */
- from_i = index_types(from_c);
- to_i = index_types(to_c);
- for (i = 1; i<= tup_size(from_i); i++) {
- checks = tup_with(checks,
- (char *) new_check_bounds_node( (Symbol)from_i[i],
- (Symbol)to_i[i]));
- }
- }
- /* TBSL: check values of discriminants for record types. */
-
- if (tup_size(checks) > 0) {
- make_insert_node(expn, checks, copy_node(expn));
- /* This line has to be deleted in order to reuse the function
- in case of conversion of array access values
- N_TYPE(expn) = to_t; */
- }
- }
-
- static int reads_prefix(int attrkind, Symbol type1)
- /*;reads_prefix*/
- {
- /* Used to determine whether an attribute can apply to an out parameter.
- * see tests A62006d, B62006c, B85007C.
- */
-
- if (attrkind == ATTR_BASE
- || attrkind == ATTR_POS
- || attrkind == ATTR_PRED
- || attrkind == ATTR_SUCC
- || attrkind == ATTR_VAL
- || attrkind == ATTR_VALUE)
- return TRUE;
-
- if (is_access(type1)) return TRUE;
- return FALSE;
- }
-